package com.flying.io.printsteam;

import com.flying.io.TestFileInputStream;
import org.junit.Test;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @author 刘鹏飞
 * @ClassName TestPrintWiter
 * @Date 2025/2/23 20:36
 * @Created by 刘鹏飞
 * @Description 测试字符输出流 --- 打印流
 * <p>
 * 在 Java 的字符输出流中，`PrintWriter` 和 `FileWriter` 是两个不同用途的类，它们的核心区别如下：
 * <p>
 * ---
 * <p>
 * ### **1. 功能定位**
 * | **类**          | **核心功能**                                                                 |
 * |------------------|-----------------------------------------------------------------------------|
 * | **`FileWriter`** | 专用于向文件写入字符的底层流，继承自 `OutputStreamWriter`。直接操作文件，功能简单，仅支持字符或字符串的写入。 |
 * | **`PrintWriter`**| 高级字符输出流，可包装 `Writer` 或 `OutputStream`。提供格式化输出、自动刷新、按行写入、多数据类型支持等增强功能。 |
 * <p>
 * ---
 * <p>
 * ### **2. 核心区别**
 * | **特性**           | **FileWriter**                          | **PrintWriter**                                                                 |
 * |--------------------|-----------------------------------------|---------------------------------------------------------------------------------|
 * | **数据支持**        | 仅支持 `char[]` 或 `String`              | 支持所有基本类型（`int`, `double` 等）、对象（自动调用 `toString()`）、格式化输出（`printf()`） |
 * | **换行控制**        | 需手动添加换行符（如 `\n`）               | 通过 `println()` 自动换行（适配系统换行符，如 `%n` 或 `\r\n`）                   |
 * | **自动刷新**        | 不支持                                  | 可启用自动刷新（构造函数参数 `autoFlush` 设为 `true`）                           |
 * | **异常处理**        | 方法抛出 `IOException`                   | 方法不抛出 `IOException`，需通过 `checkError()` 检查错误                          |
 * | **字符编码**        | 使用平台默认编码，不可指定                | 可包装 `OutputStreamWriter` 并指定编码（如 UTF-8）                               |
 * | **典型用途**        | 简单写入少量文本                          | 复杂场景：日志记录、格式化输出、按行写入、需自动刷新                             |
 * <p>
 * ---
 * <p>
 * ### **3. 代码示例对比**
 * #### **使用 `FileWriter` 写入文件**
 * ```java
 * try (FileWriter fw = new FileWriter("file.txt")) {
 * fw.write("Hello, World!\n");  // 需手动换行
 * fw.write("Today is " + LocalDate.now());
 * } catch (IOException e) {
 * e.printStackTrace();
 * }
 * ```
 * <p>
 * #### **使用 `PrintWriter` 写入文件**
 * ```java
 * try (PrintWriter pw = new PrintWriter(new FileWriter("file.txt"), true)) {
 * pw.println("Hello, World!");  // 自动换行
 * pw.printf("Today is %s", LocalDate.now());  // 格式化输出
 * pw.println(123);  // 直接写入整数
 * } catch (IOException e) {
 * e.printStackTrace();
 * }
 * ```
 * <p>
 * ---
 * <p>
 * ### **4. 组合使用场景**
 * `PrintWriter` 通常包装 `FileWriter` 或 `OutputStreamWriter`，以增强功能：
 * ```java
 * // 指定编码（UTF-8）并启用自动刷新
 * PrintWriter pw = new PrintWriter(
 * new OutputStreamWriter(new FileOutputStream("file.txt"), StandardCharsets.UTF_8),
 * true
 * );
 * pw.println("自动刷新 + 指定编码");
 * ```
 * <p>
 * ---
 * <p>
 * ### **5. 如何选择？**
 * - **用 `FileWriter` 的场景**
 * 简单写入少量文本，无需换行控制、格式化或自动刷新。
 * <p>
 * - **用 `PrintWriter` 的场景**
 * 需要以下任一功能时：
 * - 按行写入（`println()`）
 * - 格式化输出（`printf()`）
 * - 自动刷新（`autoFlush=true`）
 * - 写入非字符串类型（如 `int`, `double`）
 * - 指定字符编码（需配合 `OutputStreamWriter`）
 * <p>
 * ---
 * <p>
 * ### **6. 关键注意事项**
 * 1. **`FileWriter` 的编码问题**
 * `FileWriter` 使用平台默认编码（如 Windows 的 GBK），可能导致乱码。若需指定编码，应改用：
 * ```java
 * // 使用 UTF-8 编码写入文件
 * Writer writer = new OutputStreamWriter(new FileOutputStream("file.txt"), StandardCharsets.UTF_8);
 * PrintWriter pw = new PrintWriter(writer);
 * ```
 * <p>
 * 2. **`PrintWriter` 的异常静默**
 * `PrintWriter` 的方法不抛出 `IOException`，需定期调用 `checkError()` 检查错误：
 * ```java
 * pw.println("Some data");
 * if (pw.checkError()) {
 * System.err.println("写入失败！");
 * }
 * ```
 * <p>
 * 3. **性能优化**
 * 自动刷新（`autoFlush=true`）会频繁调用 `flush()`，可能影响性能。高吞吐场景建议关闭自动刷新，手动调用 `flush()`。
 * <p>
 * ---
 * <p>
 * ### **总结**
 * - `FileWriter` 是轻量级的文件字符写入工具，适合简单场景。
 * - `PrintWriter` 是功能丰富的增强类，支持格式化、自动刷新、多数据类型，适合复杂输出需求。
 * - 两者常结合使用：`PrintWriter` 包装 `FileWriter` 或 `OutputStreamWriter`，兼顾灵活性与功能。
 * <p>
 * <p>
 * PrintWriter 属于处理流。虽然某些构造方法允许直接传入文件路径，但这仅是语法糖，本质上它仍在装饰内部的节点流。它的核心作用是提供格式化输出功能，而非直接对接数据源。
 */
public class TestPrintWriter {

    @Test
    public void test1() {
        try (
                // 创建字符打印流对象:
                // 可以在构造方法中 传入 参数 autoFlush=true 自动刷新
                // 自动刷新（`autoFlush=true`）会频繁调用 `flush()`，可能影响性能。高吞吐场景建议关闭自动刷新，手动调用 `flush()`
                PrintWriter pw = new PrintWriter(new FileWriter("log.txt", true));
        ) {
            //    调用不带换行的内容输出方法


            // PrintWriter可以输入的数据类型 -- boolean  char  int long float double String Object
            pw.print(true);
            pw.print(1);
            pw.print("人生苦短,珍惜当下");

            // 换行输出

            pw.println("世界很大,我想去看看~~");

            // 手动刷新缓冲区
            pw.flush();


        } catch (IOException e) {
            e.printStackTrace();
        }


    }


    // 通过 字符输出流 --
    // PrintWriter: 字符输出流
    // 常说的打印流式 PrintStream

    // 通过字符输出流添加行号
    @Test
    public void test2() {

        try (   //  输入流对象
                BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("独白.txt"), "gbk"));
                // 输出流对象
                PrintWriter pw = new PrintWriter("独白2.txt");
        ) {

            //
            String s="";
            int i=1;
            while ((s=br.readLine())!=null){
                pw.println(i+".\t "+s);
                i++;
            }

            pw.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }


    }


}


